use strict;

my $dir_state = "SameDir";
our $cur_dir_path = "";
our $old_dir_path = "";
my @dir_content = ();                #Initailize the array
my @old_dir = ();
my ($has_files, $has_real_files, $has_dirs, $has_meta_files, $has_meta_dirs) = (0, 0, 0, 0, 0);
my $cur_dir_size = 0;
my $is_dir_updated = "no";
my %file_type_stat = ();
my (%file_num_pre, %file_num_suf, %dir_num_pre, %dir_num_suf);
my $site_id;
our (%dir_files, %new_item_hash, %old_item_hash);

my $site_os = "";
my $total_site_files = 0;
my $total_site_size = 0;
my $first_run = "yes";
my %site_file_type = ();
my @date_time = gmtime(time);
$date_time[5] += 1900;

my $root_dir = "";

sub process_site_dir{
        #initialize
        my ($dir_ref, $list_site, $down_site, $first) = @_;
        $first_run = $first;
        $site_id = $down_site->{'site_id'};
        my $site = $down_site->{'site_dns_name'};
        $root_dir = $dir_ref->{'dir_path'};
        $dir_state = "SameDir";

        #Loop for every directory or file in the file list of one site.
        while($dir_state ne "NoMore"){
                init_state();
                get_dir_content($dir_state);
                $dir_state = judge_dir_state();
                parse_dir_content($dir_state, $list_site->{'site_dns_name'});

                last if $dir_state eq "NoMore";

                if($dir_state eq "DirDel"){
                        print "Del Resource Path $old_dir_path\n";
                     #   del_res_path($old_dir_path, $site_id);
                        next;
                                        }
                  }

}

sub init_state{
        $cur_dir_path = "";
        $old_dir_path = "";
        $has_files = $has_real_files = $has_dirs = $has_meta_files = $has_meta_dirs = 0;
        $cur_dir_size = 0;
        $is_dir_updated = "no";
        %file_type_stat = ();
}

#Read the new file and old file(if exists)
#and push directories in the two files into two arrays.
#The two arrays are: @dir_content and @old_dir
sub get_dir_content{
        my $dir_state = shift;
        if($first_run eq "yes" || $dir_state eq "SameDir" || $dir_state eq "NewDir"){
                @dir_content = ();
                %dir_files = ();
                %new_item_hash = ();
                while(<IN>){ #<IN>=new file descriptor
                        s/[\r\n]//g;  #RE: eliminate all '\r\n's
                        last if($_ eq "");  #end
                        push @dir_content, $_;  #push current into @dir_content
                }
        }
         #not first time,old file already exists
        if($first_run eq "no" and ($dir_state eq "SameDir" || $dir_state eq "DirDel")){
                @old_dir = ();
                %old_item_hash = ();
                while(<OLDIN>){ #<OLDIN>=old file descriptor
                        s/[\r\n]//g;
                        last if($_ eq "");
                        push @old_dir, $_;
                }
        }
}


#Judge the state of the directory
#Four directory states are defined:
#SameDir: remains the same
#NewDir: a new directory
#DirDel: has been deleted on the site
#NoMore: end 
sub judge_dir_state{
        $cur_dir_path = $dir_content[0];  #fetch first diretory path
        $cur_dir_path =~ s/:$/\//g;   #replace '/' in the end of the string by ':'
        $cur_dir_path =~ s|^//$|/|g;  #replace '//' by '/' (to root directory)
        $cur_dir_path =~ s|//$|/|g;
        $dir_content[0] = $cur_dir_path;


        my @state_array =qw(NewDir SameDir DirDel NoMore);  # Defines the four states.

        if($first_run eq "yes" and $cur_dir_path ne ""){
                return $state_array[0];  #first time,always NewDir
        } 

        $old_dir_path = $old_dir[0];  #same as up
        $old_dir_path =~ s/:$/\//g;
        $old_dir_path =~ s|^//$|/|g;
        $old_dir_path =~ s|//$|/|g;
        $old_dir[0] = $old_dir_path;

        my $state = (lc $cur_dir_path) cmp (lc $old_dir_path); #convert to lowercase strings and compare
        
        #When end of the array reached, extra analysis is needed
        if($cur_dir_path eq ""){
                return $state_array[3] if $state == 0;
                return $state_array[2] if $state == -1;
        }
        if($old_dir_path eq ""){
                return $state_array[3] if $state == 0;
                return $state_array[0] if $state == 1;
        }
        return $state_array[$state+1];
}

#According to different directory states
#call different functions
sub parse_dir_content{
        my ($dir_state, $site) = @_;
        if($dir_state eq "SameDir"){  #Directory name is the same,check subdirectories
                compare_old_dir($site);
        }elsif($dir_state eq "NewDir"){   #Insert new directory
                insert_new_dir($site);
        }elsif($dir_state eq "DirDel"){   #delete old directory
                delete_old_dir($site);
        }
}


#Insert new directory and all its subdirectories and files
# into table vf_files
sub insert_new_dir{
        my $site = shift;
        my($item_name, $item_attr, $new_index);

        #Loop:one time a subdirectory or a file
        for($new_index = 1; $new_index <= $#dir_content; $new_index++){
                ($item_name, $item_attr) = parse_item($dir_content[$new_index], 1);
                $new_item_hash{$item_name} = $item_attr;
                op_file_db("NewItem", $item_name, $site, $site_id, $root_dir);
        }
        commit_db();
        #op_file_db("NoMore") if $first_run ne "yes";
}

#Delete a directory that has been deleted on the site
sub delete_old_dir{
        my $site = shift;
        my ($item_name, $item_attr) = parse_item($old_dir[0], 0);
        op_file_db("DirDel", $old_dir[0], $site, $site_id, $root_dir);

        #op_file_db("NoMore") if $first_run ne "yes";
}

#Compare subdirectories of two directories with same names
sub compare_old_dir{
        my $site = shift;
         my ($new_index, $old_index, $item_name, $item_attr);
        my $item_state = "SameItem";

        #Get subdirectories or files from the new file
        for($new_index = 1; $new_index <= $#dir_content; $new_index++){
                ($item_name, $item_attr) = parse_item($dir_content[$new_index], 1);
                %new_item_hash = (%new_item_hash, $item_name, $item_attr);
        }
        $new_index = 0;

        #Get subdirectories or files from the old file
        for($old_index = 1; $old_index <= $#old_dir; $old_index++){
                ($item_name, $item_attr) = parse_item($old_dir[$old_index], 0);
                %old_item_hash = (%old_item_hash, $item_name, $item_attr);
        }
        $old_index = 0;

        #Sort
        my @new_item_names = sort keys %new_item_hash;
        my @old_item_names = sort keys %old_item_hash;

        #Loop : Compare one subdirectory a time and call proper functions
        while($item_state ne "NoMore"){
                $item_state = judge_item_state($new_item_names[$new_index], $old_item_names[$old_index]);
                if($item_state ne "ItemDel"){
                        op_file_db($item_state,$new_item_names[$new_index], $site, $site_id, $root_dir);
                }else{
                        op_file_db($item_state,$old_item_names[$old_index], $site, $site_id, $root_dir);
                }
                last if $item_state eq "NoMore";
                $is_dir_updated = "yes" if $item_state ne "SameItem";
                if($item_state eq "NewItem"){
                        $new_index ++;
                }elsif($item_state eq "ItemDel"){
                        $old_index ++;
                }else{
                        $dir_files{$new_item_names[$new_index]} .= " old" if exists($dir_files{$new_item_names[$new_index]});
                        $new_index ++;
                        $old_index ++;
                }
        }
}

#Judge item(file) state
#Four item_states defined:
#NewItem: a new file
#SameItem: the same file
#UpItem: file needs to be updated
#NoMore: end
sub judge_item_state{
        my ($new_name, $old_name) = @_;
        my @item_state_array = qw(NewItem SameItem ItemDel UpItem NoMore);

        my $state = $new_name cmp $old_name;
        if($new_name eq ""){
                return $item_state_array[4] if $state == 0;
                return $item_state_array[2] if $state == -1;
        }
        if($old_name eq ""){
                return $item_state_array[4] if $state == 0;
                return $item_state_array[0] if $state == 1;
        }
        return $item_state_array[$state+1] if $state != 0;
        if($new_item_hash{$new_name} ne $old_item_hash{$old_name}){
                return $item_state_array[3];
        }else{
                return $item_state_array[1];
        }
}

#Parse every item's attribute
sub parse_item{
        my ($item, $n_o) = @_;
        my ($mode, $links, $user, $group, $size,
                        $month, $day, $t_or_y, $name) = split(/\s+/, $item , 9);
        my $is_dir = 0;
        my ($year , $time, $date, $stamp);

        my %month2num = ('Jan', '01',
                         'Feb', '02',
                         'Mar', '03',
                         'Apr', '04',
                         'May', '05',
                         'Jun', '06',
                         'Jul', '07',
                         'Aug', '08',
                         'Sep', '09',
                         'Oct', '10',
                         'Nov', '11',
                         'Dec', '12',);
        $month = $month2num{$month};
        if($t_or_y =~ /:/){
                $year = $date_time[5];
                $time = $t_or_y;
        }else{
                $year = $t_or_y;
                $time = "00:00";
        }                   
        $year = "1900" if($year le "1971");
        if($mode =~ /^d/){                 
                $is_dir = 1;
                if($n_o){               
                        $has_dirs ++;
                        if($site_os){
                                $site_os = "Windows" if $size eq "0";
                                $site_os = "Unix-like";
                        }
                        dir_stat($name);
                }
        }else{                                  
                if($n_o){
                        $has_files ++;
                        $has_real_files ++ if $size ne "0";
                        $total_site_files ++;

                        $total_site_size += $size;
                        $cur_dir_size += $size;
                        
              
                        if($mode =~ /^-/){        
                                my $f_date = join("-", $year, $month, $day);
                                $dir_files{$name} = join(" ", $size, $f_date, $time);
                                if($name =~ /\.([\w\d]+)$/){
                                        #        $file_type_stat{lc $1}++ if $in_res eq "no";
                                        $file_type_stat{lc $1}++;
                                        $site_file_type{lc $1}++;
                                }

                        }
                }
        }
        $stamp = sprintf("%d-%02d-%02d %s", $year, $month, $day, $time);
        $date = join("-", $year, $month, $day);
        return ($name, join(" ", $size, $date, $time, $is_dir));
}


sub dir_stat{
        my $name = shift;

        $name =~ s/(\.(v|ver)*\d+)+$//;
        if($name =~ /.*\.*Season(\d+)/i){
                $name =~ s/$1//;
        }

        if($name =~ /^\[LilyStudio\]|^Done$|^\[yaoge123\]|\[EEA\]/i){
                $has_meta_dirs ++;
        }
}

1;